﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using MySql.Data.MySqlClient;

namespace 装甲部队验证服务端
{
    public partial class Form1 : Form
    {
        public string MysqlAddress;
       // public int Prot=3306;
        public string UserName;
        public string PassWord;
        public string DataBase;

        public string socketport;
        MySqlConnection conn;//mysql的连接
        private Socket serverSocket;//服务端套接字
        private Thread listenThread;
        private Socket socket;
        private Thread threadReceive;
        Heatsend heatsend = new Heatsend();
        Dictionary<string, long> Isconn = new Dictionary<string, long>();//记录每一个客户端的连接状态,前面为IP,后面是接收的时间

        public Form1()
        {
            InitializeComponent();
            IpBox.Text = GetLocalIP();
        }

        private void StratService_Click(object sender, EventArgs e)
        {
            MysqlAddress = Address.Text;
            DataBase = DataName.Text;
            UserName = User.Text;
            PassWord = Pass.Text;
            socketport = PortBox.Text;
            ConsoleBox.Text = "开始启动";

            if(CoonMysql())
            {
                StartSocket();
                
            }
            
           // StartSocket();
        }

        private bool CoonMysql()
        {
            string connstr = "data source=" + MysqlAddress + ";database=" + DataBase + ";user id=" + UserName + ";password=" + PassWord + ";pooling=false;charset=utf8";//pooling代表是否使用连接池
            conn = new MySqlConnection(connstr);
            try
            {
                conn.Open();//打开通道，建立连接，可能出现异常,使用try catch语句
                ConsoleBox.Text = "数据库成功建立连接 \r\n";
                return true;
                //在这里使用代码对数据库进行增删查改
            }
            catch (MySqlException ex)
            {
                Console.WriteLine(ex.Message);
                ConsoleBox.Text = "数据库连接失败\r\n";
                return false;
            }
        
        }

        private bool mysql_cmd(string sql, MySqlConnection conn)
        {
            try
            {
                MySqlCommand cmd = new MySqlCommand(sql, conn);
                MySqlDataReader reader = cmd.ExecuteReader();
                reader.Close();
                
                return true;
            }
            catch(Exception e)
            {
                Invoke(new Action(() => { ConsoleBox.Text += e+" \r\n"; }));
                return false;
            }
        }

        private string Mysql_Sql(string sql, MySqlConnection conn,string fliter)
        {
            string ind= string.Empty;
            try
            {
                MySqlCommand cmd = new MySqlCommand(sql, conn);
                MySqlDataReader reader = cmd.ExecuteReader();//执行ExecuteReader()返回一个MySqlDataReader对象
                while (reader.Read())//初始索引是-1，执行读取下一行数据，返回值是bool
                {
                    //Console.WriteLine(reader[0].ToString() + reader[1].ToString() + reader[2].ToString());
                    //Console.WriteLine(reader.GetInt32(0)+reader.GetString(1)+reader.GetString(2));
                    //Console.WriteLine( reader.GetString("username") + reader.GetString("password"));//"userid"是数据库对应的列名，推荐这种方式
                    ind = reader.GetString(fliter);
                  
                }
                reader.Close();
                   return ind;
            }
            catch
            {

            }
            
            return string.Empty;
        }


        private void StartSocket()
        {
            IPAddress ip = IPAddress.Parse(GetLocalIP());//设置IP
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//实例化套接字
            try
            {                //绑定ip和端口                
                serverSocket.Bind(new IPEndPoint(ip, Convert.ToInt32(socketport)));                
                serverSocket.Listen(10);  //设置最多同时监听（排队人数最多多少），先准备10个挂起的socket(连接)，用不用，先放那，用的时候直接取即可                           
                listenThread = new Thread(ListenClientConnect);//开一个线程监听
                listenThread.Start();
                ConsoleBox.Text += "服务器开启成功，开始监听 \r\n";
                StratService.Enabled = false;



            } catch
            {
               ConsoleBox.Text += "服务器开启失败 \r\n"; 
              
            }            

            }

        private void ListenClientConnect()
        {
            while (true)//这个线程是死循环，一直执行
            {
                socket = serverSocket.Accept();      //如果接收到了套接字，赋值后继续执行              
                threadReceive = new Thread(Receive);//开一个新线程，来处理受到的套接字(连接)，新线程执行Receive方法
                threadReceive.Start(socket);//为Receive(Socket socket)传入参数，并启动线程
                Socket myClientSocket = (Socket)socket;
                IPEndPoint clientipe = (IPEndPoint)myClientSocket.RemoteEndPoint;
                string ip = clientipe.Address.ToString();
                Invoke(new Action(() => { ConsoleBox.Text += ip+" 已连接 \r\n"; }));
                
            }
        }

     
        private void Receive(object socket)
        {
            try {
                Socket myClientSocket = (Socket)socket;
                IPEndPoint clientipe = (IPEndPoint)myClientSocket.RemoteEndPoint;
                string ip = clientipe.Address.ToString();
                Dictionary<string, string> verfy = new Dictionary<string, string>();
                bool isstart =true;
                long Lastrevicetime=0;
                int keyindex;
                Isconn.Add(ip, heatsend.NowTime());
                threadReceive = new Thread(Isconnect);//开一个新线程，来处理受到的套接字(连接)，新线程执行Receive方法
                threadReceive.Start(socket);
                while (true)
                {
                    //IsConnectsend(isstart);
                    byte[] buff = new byte[20000];//新建一个数据缓存
                    int bufflength = myClientSocket.Receive(buff);//将套接字信息存入数据缓存,并且返回数据长度
                    string str = Encoding.UTF8.GetString(buff, 0, bufflength);//将数据转为字符串
                    if (!str.Equals(string.Empty))//防止意外退出
                    {
                        Isconn[ip] = heatsend.NowTime();
                        //Invoke(new Action(() => { ConsoleBox.Text = "收到数据  时间为" + heatsend.NowTime() + " 数据是 " + str + "\r\n"; }));
                    }
                    if (!str.Equals(string.Empty))
                    {
                        keyindex = Convert.ToInt32(str.Substring(0, 1));
                        if (str.Equals("退出"))
                        {
                            Invoke(new Action(() => { ConsoleBox.Text += verfy["账号"] + " 已经断开连接\r\n"; }));
                            break;
                        }
                        if (!verfy.ContainsKey(str.Substring(1, keyindex)))
                        {
                            verfy.Add(str.Substring(1, keyindex), str.Substring(keyindex+1));
                        }
                        else
                        {
                            verfy[str.Substring(1, keyindex)] = str.Substring(keyindex+1);
                        }
                    }
                    Checkpass(verfy);
                    Register(verfy);
                }
            }
            catch(Exception e)
            {
             
            }

            
        }

        private void Isconnect(object socket)
        {
            long Lasttime;
            long Maxtime=5000;
            Socket myClientSocket = (Socket)socket;
            IPEndPoint clientipe = (IPEndPoint)myClientSocket.RemoteEndPoint;
            string ip = clientipe.Address.ToString();
            while (true)
            {
                if ( heatsend.NowTime()- Isconn[ip] > Maxtime)
                {
                    Invoke(new Action(() => { ConsoleBox.Text += ip+ ": 客户端已经断开 \r\n"; }));
                    myClientSocket.Shutdown(SocketShutdown.Both);
                    myClientSocket.Close();
                    break;
                }
            }
        }

        private void Register(Dictionary<string, string> verfy)
        {
            if(verfy.ContainsKey("注册账号") && verfy.ContainsKey("注册密码"))
            {
                string sql = "INSERT INTO sign_info VALUES('"+verfy["注册账号"]+"', '"+ verfy["注册密码"] + "')";
                if (mysql_cmd(sql, conn))
                {
                    SendMsg("注册成功");
                    verfy.Remove("注册账号");
                    verfy.Remove("注册密码");
                }
                else
                {
                    SendMsg("注册失败");
                    verfy.Remove("注册账号");
                    verfy.Remove("注册密码");
                }

            }
            
        }

        private void Checkpass(Dictionary<string, string> verfypass)
        {
            if (verfypass.ContainsKey("密码") && verfypass.ContainsKey("账号"))
            {
                string sql = "select password from Sign_info where user_name='" + verfypass["账号"] + "'";
                if (verfypass["密码"].Equals(Mysql_Sql(sql, conn, "password")))
                {
                    SendMsg("验证成功");
                    Invoke(new Action(() => { ConsoleBox.Text += ConsoleBox.Text += "验证成功,进入游戏\r\n"; }));
                    verfypass.Remove("账号");
                    verfypass.Remove("密码");
                }
                else
                {
                    SendMsg("验证失败");
                    Invoke(new Action(() => { ConsoleBox.Text += ConsoleBox.Text += "真密码 ："+ verfypass["账号"] + "验证失败，密码："+ verfypass["密码"]+"     真密码 ："+ Mysql_Sql(sql, conn, "password\r\n"); }));
                    verfypass.Remove("账号");
                    verfypass.Remove("密码");

                }
            }
         
         }




        private void SendMsg(string str)
        {
            try
            {
                string strMsg = str;
                byte[] buffer = new byte[20000];
                buffer = Encoding.UTF8.GetBytes(strMsg);//将字符串转为缓存数据
                socket.Send(buffer);//发送此数据
                
            } catch
            {
                MessageBox.Show("发送数据失败", "发送数据失败");
            }


        }
        public static string GetLocalIP()
        {
            try
            {
                string HostName = Dns.GetHostName(); //得到主机名
                IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
                for (int i = 0; i < IpEntry.AddressList.Length; i++)
                {
                    if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                    {
                        return IpEntry.AddressList[i].ToString();
                    }
                }
                return "";
            }
            catch (Exception ex) 
            {
                return "获取本机IP出错:" + ex.Message.ToString();
            }
        }

        private void MainForm_Closing(object sender, CancelEventArgs e)
        {
            System.Environment.Exit(0);
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            this.FormClosing += new FormClosingEventHandler(MainForm_Closing);
            
        }
    }

    
}
